#pragma once
#include "Thread.hpp"
#include "LockGuard.hpp"
#include <vector>
#include <queue>
#include <unistd.h>

template<class T>
class ThreadPool;
template<class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T>* tp,Thread* td)
    :_tp(tp),_td(td)
    {
    }
    ThreadPool<T>* _tp;
    Thread* _td;
};


template<class T>
class ThreadPool
{
private:
    static void* start_routine(void* args)
    {
        ThreadData<T>* td = static_cast<ThreadData<T>*>(args);   //拿到threadpool的指针
        ThreadPool<T>* tp = td->_tp;            //拿到当前thread的指针
        T task;
        Thread* t = td->_td;
        while(true)
        {    
            {                                     //控制LockGuard的生命周期，拿到任务后就不需要锁保护了。
                LockGuard lock(&tp->_mutex);
                while(tp->QueueIsEmpty())
                {
                    tp->QueueWait();
                }
                tp->QueuePop(task);
            }
            std::cout<< t->ThreadName()<<":";
            task();
        }
       
    }
    

public:
    ThreadPool(const int num = 3)   //默认初始创建三个线程
    :_num(num),_tp(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<_num;++i)
        {
            Thread* t = new Thread;
            _tp[i] = t;
        }
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for(const auto& e : _tp)
        delete e;
    }


    void start() //启动线程池获取任务，处理任务
    {
        for(int i=0;i<_num;++i)
        {
            ThreadData<T>* Td = new ThreadData<T>(this,_tp[i]);
            _tp[i]->Run(start_routine,Td);
        }
    }

    void Push(const T& in)      //输入的任务
    {
        LockGuard lock(&_mutex);
        _task.push(in);
        QueueSignal();
    }

    bool QueueIsEmpty()
    {
        if(_task.empty())
        {
            return true;
        }
        return false;
    }
private:
    void QueuePop(T& task)
    {
        task = _task.front();
        _task.pop();
    }
    void QueueWait()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    void QueueSignal()
    {
        pthread_cond_signal(&_cond);
    }


private:
    int _num;         //线程池内创建多少个线程
    std::vector<Thread*> _tp;
    std::queue<T> _task;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};